﻿יצירת קוד אוטומטית
=========================

החל מגרסא 1.1.2, Yii מצויידת עם מערכת מבוססת ווב ליצירת קוד בשם *Gii*. מערכת זו הינה תחליף עבור הכלי הקודם בשם `yiic shell` שרץ על גבי שורת הפקודות. בחלק זה, אנו נדגים כיצד להשתמש ב-Gii וכיצד להרחיב את Gii כדי לזרז את תהליך הפיתוח.

שימוש ב-Gii
---------

Gii מיושמת במונחים של מודול וחייבת להיות בשימוש תחת אפליקצית Yii קיימת. כדי להשתמש ב-Gii, אנו קודם עורכים את הגדרות האפליקציה בצורה הבאה:

~~~
[php]
return array(
    ......
    'modules'=»array(
        'gii'=»array(
            'class'=»'system.gii.GiiModule',
            'password'=»'סיסמא כלשהי',
            // 'ipFilters'=»array(...רשימה של כתובות אייפי...),
            // 'newFileMode'=»0666,
            // 'newDirMode'=»0777,
        ),
    ),
);
~~~

בקוד המוצג למעלה, אנו מגדירים מודול בשם `gii` שהמחלקה שלו הינה [GiiModule]. כמו כן אנו מגדירים סיסמא עבור המודול שאנו נצטרך להזין בעת הכניסה ל-Gii.

כברירת מחדל ומטעמי בטחון, Gii מוגדרת ככה שיהיה ניתן לגשת אל המודול רק משרת `localhost`. אם אנו רוצים לאפשר גישה למחשבים בטוחים נוספים, אנו יכולים להגדיר את המאפיין [GiiModule::ipFilters] כפי שמוצג בקוד למעלה.

בגלל ש-Gii יוצר קוד ושומר אותו בקבצים חדשים באפליקציה הנוכחית, אנו צריכים לוודא ששרת הווב מכיל את ההרשאות המתאימות לבצע פעולות אלו. בקוד המוצג למעלה המאפיינים [GiiModule::newFileMode] ו [GiiModule::newDirMode] שולטים באופן שבו הקבצים החדשים והתיקיות נוצרים.

» Note|הערה: Gii נועד בעיקר ככלי פיתוח. לכן, רצוי להתקינו על סביבת פיתוח. מאחר וכלי זה יכול לייצר קבצי PHP חדשים באפליקציה, אנו צריכים לשים לב לאמצעי האבטחה שבו (לדוגמא סיסמא, כתובות IP).

כעת אנו יכולים לגשת למערכת Gii דרך הקישור `http://hostname/path/to/index.php?r=gii`. כאן אנו מניחים שהקישור `http://hostname/path/to/index.php` הוא הקישור לכניסה לאפליקצית ה-Yii הנוכחית.

במידה והאפליקציה הנוכחית משתמשת בפורמט `path` עבור הקישורים (ראה [ניהול קישורים](/doc/guide/topics.url)), אנו יכולים לגשת למודול Gii דרך הקישור `http://hostnamepath/to/index.php/gii`. אנו נצטרך להוסיף את הכללים הבאים לראש הכללים הקיימים באפליקציה:

~~~
[php]
'components'=»array(
    ......
    'urlManager'=»array(
        'urlFormat'=»'path',
        'rules'=»array(
            'gii'=»'gii',
            'gii/«controller:\w+»'=»'gii/«controller»',
            'gii/«controller:\w+»/«action:\w+»'=»'gii/«controller»/«action»',
            ...כללים נוכחים...
        ),
    ),
)
~~~

Gii מגיעה עם כמה אפשרויות ליצירת קוד כברירת מחדל. כל אפשרות יצירת קוד אחראית ליצירת קוד ספציפי. לדוגמא, אפשרות יצירת הקונטרולר יוצרת מחלקת קונטרולר ביחד עם כמה קבצי תצוגה עבור פעולות; אפשרות יצירת המודל יוצרת מחלקת ActiveRecord עבור טבלה במסד הנתונים.

רצף העבודה הבסיסי לשימוש באפשרות יצירת קוד הינה:

1. כניסה לעמוד יצירת הקוד;
2. מילוי שדות המגדירות את הפרמטרים עבור יצירת הקוד. לדוגמא, בכדי להשתמש באפשרות יצירת קוד מודול כדי ליצור מודול חדש, יש לציין את המזהה יחודי עבור המודול;
3. יש ללחוץ על כפתור `Preview` בכדי לצפות בתצוגה המקדימה עבור הקוד שיווצר. תוכל לראות טבלה המציגה רשימה של קבצים ליצירה. ניתן ללחוץ על כל אחד מהם בכדי לצפות בתצוגה המקדימה של הקוד;
4. יש ללחוץ על כפתור `Generate` כדי ליצור את הקבצים;
5. יש לעיין בהודעות התיעוד של יצירת הקוד.

הרחבת Gii
-------------

למרות שאפשרויות יצירת הקוד המגיעות כברירת מחדל עם Gii הינם רחבות, אנו בדרך כלל נרצה להתאים אותם אישית או ליצור אפשרויות חדשות אשר תואמות לדרישות ולטעם שלנו. לדוגמא, אנו נרצה שהקוד שנוצר יהיה בסגנון שלנו, או שאנו נרצה שהקוד שנוצר יהיה נתמך תחת כמה שפות שונות. ניתן להשיג את כל אלו בעזרת Gii.

ניתן להרחיב את Gii בשני דרכים: התאמה אישית של התבניות הקיימות ליצירת הקוד, וכתיבת אפשרויות יצירת קוד חדשות.

### מבנה אפשרות יצירת קוד

אפשרות יצירת קוד נמצאת בתיקיה ששמה הוא שם אפשרות היצירה עצמה. התיקיה בדרך כלל מכילה את התוכן הבא:

~~~
model/                       התיקיה הראשית לאפשרות יצירת המודל
   ModelCode.php             קוד המודל אשר יוצר את הקוד
   ModelGenerator.php        קונטרולר יצירת הקוד
   views/                    מכיל קבצי תצוגה עבור אפשרות יצירת הקוד
      index.php              קובץ תצוגה ברירת המחדל
   templates/                מכיל תבניות קוד
      default/               תבנית ברירת המחדל
         model.php           תבנית הקוד לאפשרות יצירת קוד עבור מחלקת מודל
~~~

### נתיב חיפוש של אפשרויות היצירה

Gii מחפש אחר אפשרויות יצירה תחת תיקיות מסויימות המוגדרות בעזרת המאפיין [GiiModule::generatorPaths]. כשיש צורך בהתאמה אישית, אנו יכולים להגדיר מאפיין זה בהגדרות האפליקציה בצורה הבאה,

~~~
[php]
return array(
    'modules'=»array(
        'gii'=»array(
            'class'=»'system.gii.GiiModule',
            'generatorPaths'=»array(
                'application.gii',   // נתיב מקוצר
            ),
        ),
    ),
);
~~~

ההגדרות המוצגות למעלה מורות ל-Gii לחפש אחר אפשרויות יצירת קוד תחת התיקיה בנתיב המקוצר `application.gii`, בנוסף לתיקית ברירת המחדל `system.gii.generators`.

ניתן לשמור אפשרויות יצירת קוד באותו השם אך בנתיבי חיפוש שונים. במקרה זה, אפשרות היצירה שצויינה קודם לכן תחת התיקיה שהוגדרה במאפיין [GiiModule::generatorPaths] תקבל עדיפות.

### התאמת תבניות קוד

זוהי הדרך הקלה ביותר והנפוצה ביותר להרחבת Gii. אנו משתמשים בדוגמא בכדי להסביר כיצד להתאים אישית את תבניות הקוד. נניח שאנו רוצים להתאים אישית את הקוד הנוצר על ידי אפשרות יצירת מודל.

אנו קודם יוצרים תיקיה בשם `protected/gii/model/templates/compact`. כאן `model` אומר שאנו עומדים *לדרוס* את אפשרות יצירת המודל המגיעה כברירת מחדל עם המערכת. ו `templates/compact` אומר שאנו מוסיפים תבנית חדשה בשם `compact`.

לאחר מכן אנו עורכים את קובץ הגדרות האפליקציה כדי להוסיף `application.gii` למאפיין [GiiModule::generatorPaths], כפי שמוצג בחלק הקודם.

כעת יש לפתוח את עמוד יצירת קוד המודל. לחיצה על שדה `Code Template`. אנו נוכל לראות רשימה אשר מכילה את תיקית התבנית שהרגע יצרנו בשם `compact`. אך אם נבחר את התבנית הזו עבור אפשרות יצירת הקוד, אנו נראה שגיאה. זה מכיוון שעדיין לא הוספנו שום קובץ המשמש כתבנית קוד בתיקית התבניות החדשה שהוספנו בשם `compact`.

יש להעתיק את הקובץ מהנתיב `framework/gii/generators/model/templates/default/model.php` אל `protected/gii/model/templates/compact`. כעת אם ננסה ליצור שום פעם עם התבנית `compact`, זה אמור לעבוד. למרות, שהקוד שיווצר הוא לא שונה מהקוד שנוצר על ידי תבנית ברירת המחדל בשם `default` מאחר ומשם העתקנו את הקובץ אך לא בצענו בו שינויים כלשהם.

כעת זה הזמן לבצע את עבודת ההתאמה האמיתית. פתח את הקובץ `protected/gii/model/templates/compact/model.php` כדי לערוך אותו. זכור שקובץ זה יהיה בשימוש כקובץ תצוגה, שאומר שהוא יכול להכיל ביטויים ב-PHP. הבא ונערוך את התבנית כדי שהמתודה `()attributeLabels` בקוד שנוצר תשתמש ב-`()Yii::t` כדי לתרגם את תוויות המאפיינים:

~~~
[php]
public function attributeLabels()
{
    return array(
«?php foreach($labels as $name=»$label): ?»
            «?php echo "'$name' =» Yii::t('application', '$label'),\n"; ?»
«?php endforeach; ?»
    );
}
~~~

בכל תבנית קוד, אנו יכולים לגשת לכמה משתנים המוגדרים מראש. כמו למשל `labels$` בדוגמא למעלה. משתנים אלו נוצרים על ידי אפשרות יצירת הקוד המקביל לקובץ התצוגה. אפשרויות יצירה שונות מספקות משתנים שונים בתבניות הקוד שלהן. יש לקרוא את התיאור בתבניות הקוד ברירת המחדל בהרחבה.

### הוספת אפשרות יצירת קוד

בחלק זה, אנו מציגים כיצד ניתן ליצור אפשרות יצירת קוד היוצרת מחלקת וידג'ט חדשה.

אנו קודם יוצרים תיקיה בשם `protected/gii/widget`. תחת תיקיה זו, אנו ניצור את הקבצים הבאים:

* `WidgetGenerator.php`: מכיל את מחלקת הקונטרולר `WidgetGenerator`. זהו הקובץ הראשי של אפשרות יצירת הוידג'ט.

* `WidgetCode.php`: מכיל את מחלקת המודל `WidgetCode`. מחלקה זו מכילה את הלוגיקה העיקרית ליצירת קוד.

* `views/index.php`: קובץ התצוגה המציג את טופס אפשרות יצירת הקוד.

* `templates/default/widget.php`: קובץ הקוד ברירת המחדל ליצירת מחלקת הוידג'ט.


#### יצירת `WidgetGenerator.php`

קובץ ה-`WidgetGenerator.php` הוא פשוט מאוד. הוא מכיל את הקוד הבא בלבד:

~~~
[php]
class WidgetGenerator extends CCodeGenerator
{
    public $codeModel='application.gii.widget.WidgetCode';
}
~~~

בקוד המוצג למעלה, אנו מציינים שאפשרות היצירה תשתמש במחלקת מודל שהנתיב שלה הוא `application.gii.widget.WidgetCode`. המחלקה `WidgetGenerator` מרחיבה את [CCodeGenerator] אשר מיישמת הרבה אפשרויות ופונקציונליות, הכוללות את פעולות הקונטרולר הדרושות לתיאום תהליך יצירת הקוד.

#### יצירת `WidgetCode.php`

קובץ `WidgetCode.php` מכיל את מחלקת המודל `WidgetCode` המכילה את הלוגיקה העיקרית ליצירת מחלקת וידג'ט המבוססת על נתוני ההזנה של המשתמש. בדוגמא זו, אנו מניחים שהנתונים שאנו מצפים מהמשתמש הם רק שם המחלקה של הוידג'ט. הקוד עבור `WidgetCode` נראה כך:

~~~
[php]
class WidgetCode extends CCodeModel
{
    public $className;

    public function rules()
    {
        return array_merge(parent::rules(), array(
            array('className', 'required'),

            array('className', 'match', 'pattern'=»'/^\w+$/'), 

        ));
    }

    public function attributeLabels()
    {
        return array_merge(parent::attributeLabels(), array(
            'className'=»'Widget Class Name',
        ));
    }

    public function prepare()
    {
        $path=Yii::getPathOfAlias('application.components.' . $this-»className) . '.php';
        $code=$this-»render($this-»templatepath.'/widget.php');

        $this-»files[]=new CCodeFile($path, $code);
    }
}
~~~

מחלקת הקוד `WidgetCode` מרחיבה את המחלקה [CCodeModel]. בדומה למחלקת מודל רגילה, במחלקה זו אנו יכולים להגדיר מתודות `()rules` ו `()attributeLabels` כדי לאמת את הנתונים שהמשתמש מזין ולהציג תוויות עבור המאפיינים במחלקה, בהתאמה. יש לזכור שמאחר והמחלקה הבסיסית [CCodeModel] כבר מגדירה כמה כללים ותוויות, אנו צריכים לאחד אותם עם הכללים והתוויות שאנו מגדירים במחלקה זו.

המתודה `()prepare` מכינה מראש את הקוד שיווצר. המטרה העיקרית שלו היא להכין רשימת אובייקטים של [CCodeFile], כל אחד מייצג קובץ קוד שנוצר. בדוגמא שלנו, אנו צריכים רק ליצור אובייקט [CCodeFile] אחד המייצג את קובץ המחלקה של הוידג'ט הנוצר. מחלקת הוידג'ט החדשה שתווצר תמוקם תחת התיקיה `protected/components`. אנו קוראים למתודה [CCodeFile::render] כדי ליצור את הקוד עצמו. מתודה זו מכילה את תבנית הקוד כסקריפט PHP ומחזירה את תוצאת הפלט המווה את הקוד שנוצר.

#### יצירת `views/index.php`

כשברשותנו הקונטרולר (`WidgetGenerator`) והמודל (`WidgetCode`), הגיע הזמן ליצור את קובץ התצוגה `views/index.php`.

~~~
[php]
«h1»אפשרות יצירת וידג'ט«/h1»

«?php $form=$this-»beginWidget('CCodeForm', array('model'=»$model)); ?»

    «div class="row"»
        «?php echo $form-»labelEx($model,'className'); ?»
        «?php echo $form-»textField($model,'className',array('size'=»65)); ?»
        «div class="tooltip"»
           שם מחלקת המודל חייבת להכיל אותיות בלבד
        «/div»
        «?php echo $form-»error($model,'className'); ?»
    «/div»

«?php $this-»endWidget(); ?»
~~~

בקוד המוצג למעלה, אנו בעיקר מציגים טופס בעזרת הוידג'ט [CCodeForm]. בטופס זה, אנו מציגים את שדה הטקסט המהווה את הערך עבור המאפיין `className` במחלקה `WidgetCode`.

בעת יצירת הטופס, אנו יכולים לנצל שני אפשרויות אשר נמצאות בוידג'ט [CCodeForm]. האחד הוא טקסט עזרה קטן (tooltip). האחר הוא שדה טקסט דביק.

אם כבר התנסת באחד מאפשרויות יצירת הקוד הנמצאות במערכת, תוכל לשים לב שבעת קביעת פוקוס בשדה טקסט כלשהו, יופיע טקסט עזרה קטן ליד השדה. ניתן לבצע זאת בצורה פשוטה על ידי הוספת DIV עם הגדרת האלמנט 'class` בשם `tooltip` ליד השדה בו רוצים להציג את ההודעה הקטנה.

עבור שדות מסויימים, אנו נרצה לשמור את הערך התקין האחרון שהיה בהם כדי לחסוך למשתמש להזין את אותו הערך שוב ושוב בכל פעם שהם משתמשים באפשרות יצירת הקוד כדי ליצור קוד. לדוגמא השדה שבו אנו מציינים את שם המחלקה הבסיסית של הקונטרולרים באפשרות יצירת הקוד לקונטרולרים המגיע עם המערכת. שדות דביקים אלו מוצגים בהתחלה כטקסט מסומן סטטי. אם נלחץ עליהם, אם יהפכו לשדות טקסט שניתן לכתוב בהם טקסט כלשהו.

בכדי להגדיר שדה טקסט בתור שדה דביק, אנו צריכים לבצע שני דברים.

ראשית, אנו צריכים להגדיר כלל אימות בשם `sticky` עבור המאפיין המקביל במודל. לדוגמא, אפשרות יצירת קונטרולרים המגיע עם המערכת מכילה את הכללים הבאים המגדירים את המאפיינים `baseClass` ו `actions` כמאפיינים דביקים:

~~~
[php]
public function rules()
{
    return array_merge(parent::rules(), array(
        ......
        array('baseClass, actions', 'sticky'),
    ));
}
~~~

שנית, אנו צריכים להוסיף מאפיין `class` בשם `sticky` לתג `div` של שדה הטקסט בתצוגה, בצורה הבאה:

~~~
[php]
«div class="row sticky"»
   ..שדה טקסט כאן...
«/div»
~~~

#### יצירת `templates/default/widget.php`

לבסוף, אנו יוצרים את תבנית הקוד `templates/default/widget.php`. כפי שהסברנו קודם לכן, השימוש של קובץ זה הוא בדומה לקובץ תצוגה המכיל פקודות וביטויים ב PHP. בתבנית קוד, אנו תמיד יכולים לגשת למשתנה `this$` המתייחס לאובייקט של המודל. בדוגמא שלנו, `this$` מתייחס לאובייקט של `WidgetModel`. לכן אנו יכולים לשלוף את שם המחלקה שהמשתמש הזין בטופס בעזרת `this-»className$`.

~~~
[php]
«?php echo '«?php'; ?»

class «?php echo $this-»className; ?» extends CWidget
{
    public function run()
    {

    }
}
~~~

זה מסכם את החלק לגבי יצירת אפשרות יצירת קוד חדשה. כעת אנו יכולים לגשת לאפשרות יצירת הקוד שהרגע יצרנו על ידי כניסה לקישור `http://hostname/path/to/index.php?r=gii/widget`.

«div class="revision"»$Id: topics.gii.txt 2066 2010-04-11 03:54:25Z qiang.xue $«/div»